<template>
  <div 
    class="scrollText" 
    ref="outer"
    @mouseenter="handleMouseEnter"
    @mouseleave="handleMouseLeave"
  >
    <div 
      class="st-inner"
      ref="innerInfo"
      :class="{'st-scrolling': shouldScroll}"
      :style="contentStyle"
    >
      <span class="st-section" ref="inner">
        <slot>{{ text }}</slot>
      </span>
      <span 
        class="st-section" 
        v-if="shouldScroll"
      >
        <slot>{{ text }}</slot>
      </span>
    </div>
  </div>
</template>

<script>
// import { debounce } from 'lodash-es'

export default {
  name: 'ScrollX',

  props: {
    // 基础滚动速度
    baseSpeed: {
      type: Number,
      default: 50
    },
    // 是否启用自适应速度
    adaptiveSpeed: {
      type: Boolean,
      default: false
    },
    // 最小滚动时间（秒）
    minDuration: {
      type: Number,
      default: 10
    },
    // 最大滚动时间（秒）
    maxDuration: {
      type: Number,
      default: 30
    },
    // 自适应系数（影响速度变化的程度）
    adaptiveFactor: {
      type: Number,
      default: 1.5
    },
    // 是否根据内容长度自适应速度
    adaptiveSpeed: {
      type: Boolean,
      default: true
    },
    // 是否允许暂停
    pauseOnHover: {
      type: Boolean,
      default: true
    },
    // 滚动方向
    direction: {
      type: String,
      default: 'left',
      validator: value => ['left', 'right'].includes(value)
    },
    // 检查间隔
    checkInterval: {
      type: Number,
      default: 1000
    },
    // 添加防抖时间配置
    debounceTime: {
      type: Number,
      default: 200
    }
  },

  data() {
    return {
      contentWidth: 0,      // 内容宽度
      containerWidth: 0,    // 容器宽度
      isPaused: false,
      text: '',
      resizeTimer: null,
      observer: null
    }
  },

  computed: {
    // 判断是否需要滚动
    shouldScroll() {
      return this.contentWidth > this.containerWidth;
    },

    // 计算内容样式
    contentStyle() {
      if (!this.shouldScroll) {
        // 不需要滚动时，居中显示
        return {
          display: 'flex',
          justifyContent: 'center',
          transform: 'translateZ(0)'
        }
      }

      // 需要滚动时，添加动画
      const duration = this.calculateDuration();
      return {
        transform: 'translateZ(0)',
        willChange: this.shouldScroll ? 'transform' : 'auto',
        animation: `scroll ${duration}s linear infinite`,
        animationPlayState: this.isPaused ? 'paused' : 'running'
      }
    }
  },

  watch: {
    // 监听内容变化
    '$slots.default': {
      handler() {
        this.$nextTick(this.updateMeasurements);
      },
      immediate: true
    }
  },

  created() {
    // 创建防抖的检查函数
    this.debouncedCheck = this.$lodash.debounce(this.checkScroll, 200)
  },

  mounted() {
    this.$nextTick(() => {
      this.initMeasurement();
      this.initResizeObserver();
      window.addEventListener('resize', this.handleResize);
    })
  },

  beforeDestroy() {
    this.stopCheck()
    window.removeEventListener('resize', this.handleResize)
    this.debouncedCheck.cancel()
    if (this.resizeTimer) {
      clearTimeout(this.resizeTimer);
    }
    if (this.observer) {
      this.observer.disconnect();
    }
  },

  methods: {
    // 初始化测量
    initMeasurement() {
      this.updateMeasurements();
    },

    initResizeObserver() {
      // 使用 ResizeObserver 监听元素大小变化
      if (window.ResizeObserver) {
        this.observer = new ResizeObserver(this.$lodash.debounce(() => {
          this.updateMeasurements();
        }, this.debounceTime));

        if (this.$refs.outer) {
          this.observer.observe(this.$refs.outer);
        }
        if (this.$refs.inner) {
          this.observer.observe(this.$refs.inner);
        }
      }
    },

    // 更新测量数据
    updateMeasurements() {
      if (this.$refs.outer && this.$refs.inner) {
        const outerRect = this.$refs.outer.getBoundingClientRect();
        const innerRect = this.$refs.inner.getBoundingClientRect();
        
        // 只在宽度真正变化时更新
        if (this.containerWidth !== outerRect.width || 
            this.contentWidth !== innerRect.width) {
          this.containerWidth = outerRect.width;
          this.contentWidth = innerRect.width;
        }
      }
    },

    // 优化后的 resize 处理
    handleResize() {
      if (this.resizeTimer) {
        clearTimeout(this.resizeTimer);
      }
      
      this.resizeTimer = setTimeout(() => {
        this.updateMeasurements();
        this.resizeTimer = null;
      }, this.debounceTime);
    },

    /**
     * 计算滚动持续时间
     * 1. 不启用自适应：使用固定速度
     * 2. 启用自适应：根据内容长度动态调整速度
     */
    calculateDuration() {
      if (!this.shouldScroll) return 0;

      const contentWidth = this.contentWidth;
      const containerWidth = this.containerWidth;

      // 不启用自适应速度时，使用基础速度
      if (!this.adaptiveSpeed) {
        return Math.max((contentWidth / this.baseSpeed), this.minDuration);
      }

      // 启用自适应速度时的计算逻辑
      return this.calculateAdaptiveDuration(contentWidth, containerWidth);
    },

    /**
     * 计算自适应的滚动持续时间
     * 使用对数函数使速度随内容长度增加而减缓
     */
    calculateAdaptiveDuration(contentWidth, containerWidth) {
      // 计算内容超出容器的比例
      const overflowRatio = contentWidth / containerWidth;
      
      // 使用对数函数计算速度因子
      // 内容越长，速度因子越大，滚动越慢
      const speedFactor = Math.log10(overflowRatio + 1) * this.adaptiveFactor;
      
      // 计算基础持续时间
      let baseDuration = contentWidth / this.baseSpeed;
      
      // 应用速度因子
      let duration = baseDuration * speedFactor;
      
      // 确保在最小和最大持续时间之间
      return Math.min(Math.max(duration, this.minDuration), this.maxDuration);
    },

    handleMouseEnter() {
      if (this.pauseOnHover && this.shouldScroll) {
        this.isPaused = true;
      }
    },

    handleMouseLeave() {
      if (this.pauseOnHover && this.shouldScroll) {
        this.isPaused = false;
      }
    },

    startCheck() {
      this.stopCheck()
      this._checkTimer = setInterval(() => {
        this.checkScroll()
      }, this.checkInterval)
    },

    stopCheck() {
      if (this._checkTimer) {
        clearInterval(this._checkTimer)
        this._checkTimer = null
      }
    },

    checkScroll() {
      this.setText()
      this.$nextTick(() => {
        const needToScroll = this.checkOverflow()
        if (needToScroll !== this.shouldScroll) {
          this.shouldScroll = needToScroll
        }
      })
    },

    checkOverflow() {
      const outer = this.$refs.outer
      const inner = this.$refs.inner
      if (!outer || !inner) return false

      const outerWidth = outer.getBoundingClientRect().width
      const innerWidth = inner.getBoundingClientRect().width
      
      return innerWidth > outerWidth
    },

    setText() {
      if (this.$slots.default) {
        this.text = this.$slots.default
          .filter(node => node.text)
          .map(node => node.text.trim())
          .join('')
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.scrollText {
  overflow: hidden;
  white-space: nowrap;
  position: relative;
  width: 100%;
}

.st-inner {
  display: inline-block;
  position: relative;
  
  &.st-scrolling {
    .st-section {
      padding: 0 5px;
    }
    
    &::before,
    &::after {
      content: '';
      position: absolute;
      top: 0;
      width: 20px;
      height: 100%;
      z-index: 1;
      pointer-events: none;
      opacity: 0;
      transition: opacity 0.3s;
    }

    &::before {
      left: 0;
      background: linear-gradient(to right, 
        rgba(255,255,255,1) 0%,
        rgba(255,255,255,0) 100%);
    }

    &::after {
      right: 0;
      background: linear-gradient(to left, 
        rgba(255,255,255,1) 0%,
        rgba(255,255,255,0) 100%);
    }

    &:hover {
      &::before,
      &::after {
        opacity: 1;
      }
    }
  }

  // 非滚动状态下的样式
  &:not(.st-scrolling) {
    .st-section {
      padding: 0;
    }
  }
}

@keyframes scroll {
  0% {
    transform: translate3d(0, 0, 0);
  }
  100% {
    transform: translate3d(-50%, 0, 0);
  }
}
</style>